package com.cy.wangly.feign.client;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
 * @author lingyun.wang on @date 2022/2/16
 */
@Aspect
@Order(Ordered.LOWEST_PRECEDENCE - 100)
@Component
@ConditionalOnProperty(name = "log.feign.switch",havingValue = "true", matchIfMissing = true)
public class FeignExceptionAspect {
    private static Logger log = LoggerFactory.getLogger(FeignExceptionAspect.class);
    @Pointcut("@within(org.springframework.cloud.openfeign.FeignClient)")
    public void feignClientPointCut() {}

    /**
     * 配置前置通知,使用在方法aspect()上注册的切入点
     * 同时接受JoinPoint切入点对象,可以没有该参数
     * @param joinPoint
     * @throws Throwable
     */
    @Around("feignClientPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable{
        try {

            return joinPoint.proceed();
        }catch (Exception e){
            Object target = joinPoint.getTarget();
            Object handler = getFieldValueByName("h",target);
            Object clazz = getFieldValueByName("target",handler);
            Object name = getFieldValueByName("name",clazz);
            Object url = getFieldValueByName("url",clazz);
//            InvocationHandler invocationHandler = Proxy.getInvocationHandler(feignClient);
//            Field field = invocationHandler.getClass().getDeclaredField("memberValues");
//            Map memberValues = (Map) field.get(invocationHandler);
//            Object key = memberValues.get("value");
//            Object name = memberValues.get("name");
            log.error("调用feign接口出现异常！服务名:{},url:{}","TURKEY","http://172.16.3.119:5000",e);
            throw e;
        }
    }

    private Object getFieldValueByName(String fieldName, Object o) {
        try {
            String firstLetter = fieldName.substring(0, 1).toUpperCase();
            String getter = "get" + firstLetter + fieldName.substring(1);
            Method method = o.getClass().getMethod(getter, new Class[] {});
            Object value = method.invoke(o, new Object[] {});
            return value;
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            return null;
        }
    }
}
